import collections

class identitydict(collections.MutableMapping, dict):
    '''A dictionary that handle keys by identity, not value.
    
    Keys of a `identitydict` can be non-hashable types. Two keys that have the
    same value, but different identities are considered to be different keys.
    
    >>> D = identitydict()
    >>> D[[1, 2]], D[[1, 2]] = 1, 2
    >>> D
    identitydict({[1, 2]: 2, [1, 2]: 1})
    '''

    def __init__(self, iterable=(), **kwds):
        dict.__init__(self)
        self.update(iterable, **kwds)
        self._keysdict = {}

    def __delitem__(self, key):
        id_key = id(key)
        try:
            dict.__delitem__(self, id_key)
            del self._keysdict[id_key]
        except KeyError:
            raise KeyError(key)

    def __getitem__(self, key):
        return dict.__getitem__(self, id(key))

    def __iter__(self):
        return self._keysdict.itervalues()

    def __setitem__(self, key, value):
        id_key = id(key)
        dict.__setitem__(self, id_key, value)
        self._keysdict[id_key] = key

    def __repr__(self):
        return 'identitydict({%s})' % (', '.join('%s: %s' % item for item in self.items()))

    def __contains__(self, key):
        return dict.__contains__(self, id(key))

if __name__ == '__main__':
    import doctest
    doctest.testmod(optionflags=doctest.REPORT_ONLY_FIRST_FAILURE, verbose=0)

